#include <QtGui>
#include <QtNetwork>

#include "bonjourclient.h"
#include "bonjourservicebrowser.h"
#include "bonjourserviceresolver.h"

BonjourClient::BonjourClient(QWidget *parent) : QDialog(parent), bonjourResolver(0)
{
	// Setup dialog.
	bonjourBrowser = new BonjourServiceBrowser(this);
	getInfoButton = new QPushButton(tr("Get Info"));
	quitButton = new QPushButton(tr("Quit"));
	buttonBox = new QDialogButtonBox;
	tcpSocket = new QTcpSocket(this);
	QGridLayout *mainLayout = new QGridLayout;

	bonjourBrowser->setHeaderLabels(QStringList() << tr("WeaveEdit Server") << tr("Port"));

	// Setup client events.
	connect(bonjourBrowser, SIGNAL(currentBonjourRecordsChanged(const QList<BonjourRecord> &)),
		this, SLOT(updateRecords(const QList<BonjourRecord> &)));
	connect(getInfoButton, SIGNAL(clicked()), this, SLOT(requestInfo()));
	connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
	connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readInfo()));
	connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
		this, SLOT(displayError(QAbstractSocket::SocketError)));

	// Setup dialog.
	getInfoButton->setDefault(true);
	getInfoButton->setEnabled(false);

	buttonBox->addButton(getInfoButton, QDialogButtonBox::ActionRole);
	buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);

	mainLayout->addWidget(bonjourBrowser, 0, 0, 2, 2);
	mainLayout->addWidget(buttonBox, 3, 0, 1, 2);

	setLayout(mainLayout);
	bonjourBrowser->setFocus();

	// Start browsing for weaveedit servers.
	bonjourBrowser->browseForServiceType(QLatin1String("_weaveedit._tcp"));
}

/** Get the info of a server. */
void BonjourClient::requestInfo()
{
	getInfoButton->setEnabled(false);
	tcpSocket->abort();
	QTreeWidgetItem *service = bonjourBrowser->selectedItems().first();

	// No selected items, so no info to get.
	if (bonjourBrowser->selectedItems().isEmpty())
		return;

	// Setup bonjour address resolver if it hasn't been done already.
	if (!bonjourResolver)
	{
		bonjourResolver = new BonjourServiceResolver(this);

		connect(bonjourResolver, SIGNAL(bonjourRecordResolved(const QHostInfo &, int)),
			this, SLOT(connectToServer(const QHostInfo &, int)));
	}

	QVariant variant = service->data(0, Qt::UserRole);

	// Try to resolve the address given the description of the server.
	bonjourResolver->resolveBonjourRecord(variant.value<BonjourRecord>());
}

/** Connect to the server selected. */
void BonjourClient::connectToServer(const QHostInfo &hostInfo, int port)
{
	const QString address = hostInfo.hostName();

	if (!hostInfo.addresses().isEmpty())
		tcpSocket->connectToHost(address, port);
}

/** Read any info the server wants to send. */
void BonjourClient::readInfo()
{
	QString IP;
	//int port = 0;

	IP = tcpSocket->readAll();
	QMessageBox::information(this, "WeaveEdit Server Info ", IP);
	getInfoButton->setEnabled(true);
}

void BonjourClient::displayError(QAbstractSocket::SocketError socketError)
{
	switch (socketError)
	{
		case QAbstractSocket::RemoteHostClosedError:
			break;

		case QAbstractSocket::HostNotFoundError:
			QMessageBox::information(this, tr("Error"),
						 tr("The host was not found. Please check the "
						    "host name and port settings."));

			break;

		case QAbstractSocket::ConnectionRefusedError:
			QMessageBox::information(this, tr("Error"),
						 tr("The connection was refused by the peer. "
						    "Make sure the server is running, "
						    "and check that the host name and port "
						    "settings are correct."));

			break;

		default:
			QMessageBox::information(this, tr("Error"),
						 tr("The following error occurred: %1.")
						 .arg(tcpSocket->errorString()));
	}

	getInfoButton->setEnabled(true);
}

void BonjourClient::enableGetInfoButton()
{
	getInfoButton->setEnabled(bonjourBrowser->invisibleRootItem()->childCount() != 0);
}

/** Update the list of servers. This is called whenever a change to the network is made. */
void BonjourClient::updateRecords(const QList<BonjourRecord> &list)
{
	bonjourBrowser->clear();

	// Add each record.
	foreach (BonjourRecord record, list)
	{
		QVariant variant;
		QTreeWidgetItem *processItem = new QTreeWidgetItem(bonjourBrowser,
								   record.getServiceName()
								   .split('\n'));

		variant.setValue(record);
		processItem->setData(0, Qt::UserRole, variant);
	}

	if (bonjourBrowser->invisibleRootItem()->childCount() > 0)
		bonjourBrowser->invisibleRootItem()->child(0)->setSelected(true);

	enableGetInfoButton();
}
